﻿using System.Collections;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;

namespace Gmantis.Controls.Chart
{
    public class HighLowOpenCloseSeries : HighLowSeries
    {
        // Fields
        private Binding _closeValuesBinding;
        private Binding _openValuesBinding;
        protected List<object> alCl = new List<object>();
        protected List<object> alOp = new List<object>();
        private static DependencyProperty CloseValuesProperty = DependencyProperty.Register("CloseValues", typeof(DoubleCollection), typeof(HighLowOpenCloseSeries), new PropertyMetadata(null, new PropertyChangedCallback(HighLowOpenCloseSeries.CloseValuesChanged)));
        public static readonly DependencyProperty CloseValuesSourceProperty = Utils.RegisterProperty("CloseValuesSource", typeof(IEnumerable), typeof(HighLowOpenCloseSeries), new PropertyChangedCallback(DataSeries.OnChangeValues));
        private static DependencyProperty OpenValuesProperty = DependencyProperty.Register("OpenValues", typeof(DoubleCollection), typeof(HighLowOpenCloseSeries), new PropertyMetadata(null, new PropertyChangedCallback(HighLowOpenCloseSeries.OpenValuesChanged)));
        public static readonly DependencyProperty OpenValuesSourceProperty = Utils.RegisterProperty("OpenValuesSource", typeof(IEnumerable), typeof(HighLowOpenCloseSeries), new PropertyChangedCallback(DataSeries.OnChangeValues));

        // Methods
        private static void CloseValuesChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            ((DataSeries)obj).FirePropertyChanged("CloseValues");
        }

        internal override DataPoint CreateDataPoint(int i, int j)
        {
            return new HLOCDataPoint(this, i, j, this.GetDataNamesInternal());
        }

        internal override string[] GetDataNamesInternal()
        {
            return new string[] { "Values", "XValues", "LowValues", "HighValues", "OpenValues", "CloseValues" };
        }

        internal override ValueCoordinate[] GetValueCoordinates(bool check)
        {
            if (check)
            {
                return new ValueCoordinate[] { base.Check(ValueCoordinate.Y), base.Check(ValueCoordinate.X), base.Check(ValueCoordinate.Y), base.Check(ValueCoordinate.Y), base.Check(ValueCoordinate.Y), base.Check(ValueCoordinate.Y) };
            }
            return new ValueCoordinate[] { ValueCoordinate.Y, ValueCoordinate.X, ValueCoordinate.Y, ValueCoordinate.Y, ValueCoordinate.Y, ValueCoordinate.Y };
        }

        internal override double[,] GetValues()
        {
            if (base.datavalues == null)
            {
                if (base.ValueBinding == null)
                {
                    DataSeries.InitList(base.listY, base.ValuesSource, base.Values);
                }
                if (base.XValueBinding == null)
                {
                    DataSeries.InitList(base.listX, base.XValuesSource, base.XValues);
                }
                if (base.listX.Count == 0)
                {
                    for (int i = 0; i < base.listY.Count; i++)
                    {
                        base.listX.Add(i);
                    }
                }
                if (base.LowValueBinding == null)
                {
                    DataSeries.InitList(base.alLo, base.LowValuesSource, base.LowValues);
                }
                if (base.HighValueBinding == null)
                {
                    DataSeries.InitList(base.alHi, base.HighValuesSource, base.HighValues);
                }
                if (this.OpenValueBinding == null)
                {
                    DataSeries.InitList(this.alOp, this.OpenValuesSource, this.OpenValues);
                }
                if (this.CloseValueBinding == null)
                {
                    DataSeries.InitList(this.alCl, this.CloseValuesSource, this.CloseValues);
                }
                if (base.listY.Count == 0)
                {
                    base.datavalues = base.CreateValues(new IList[] { this.alOp, base.listX, base.alLo, base.alHi, this.alOp, this.alCl });
                }
                else
                {
                    base.datavalues = base.CreateValues(new IList[] { base.listY, base.listX, base.alLo, base.alHi, this.alOp, this.alCl });
                }
                if (base.isTimeValues == null)
                {
                    base.isTimeValues = new bool[6];
                }
                base.isTimeValues[0] = base.IsTimeData((base.listY.Count == 0) ? this.alOp : base.listY);
                base.isTimeValues[1] = base.IsTimeData(base.listX);
                base.isTimeValues[2] = base.IsTimeData(base.alLo);
                base.isTimeValues[3] = base.IsTimeData(base.alHi);
                base.isTimeValues[4] = base.IsTimeData(this.alOp);
                base.isTimeValues[5] = base.IsTimeData(this.alCl);
            }
            return base.datavalues;
        }

        private static void OpenValuesChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            ((DataSeries)obj).FirePropertyChanged("OpenValues");
        }

        internal override void SetResolvedValues(int index, object[] vals)
        {
            base.SetResolvedValues(index, vals);
            switch (index)
            {
                case 4:
                    this.alOp.Clear();
                    this.alOp.AddRange(vals);
                    return;

                case 5:
                    this.alCl.Clear();
                    this.alCl.AddRange(vals);
                    return;
            }
        }

        // Properties
        public Binding CloseValueBinding
        {
            get
            {
                return this._closeValuesBinding;
            }
            set
            {
                if (this._closeValuesBinding != value)
                {
                    this._closeValuesBinding = value;
                    base.Dirty = true;
                    base.FirePropertyChanged("CloseValueBinding");
                }
            }
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public DoubleCollection CloseValues
        {
            get
            {
                return (DoubleCollection)base.GetValue(CloseValuesProperty);
            }
            set
            {
                base.SetValue(CloseValuesProperty, value);
            }
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public IEnumerable CloseValuesSource
        {
            get
            {
                return (IEnumerable)base.GetValue(CloseValuesSourceProperty);
            }
            set
            {
                base.SetValue(CloseValuesSourceProperty, value);
            }
        }

        public override Binding[] MemberPaths
        {
            get
            {
                if ((((base.ValueBinding == null) && (base.XValueBinding == null)) && ((base.HighValueBinding == null) && (base.LowValueBinding == null))) && ((this.OpenValueBinding == null) && (this.CloseValueBinding == null)))
                {
                    return null;
                }
                return new Binding[] { base.ValueBinding, base.XValueBinding, base.LowValueBinding, base.HighValueBinding, this.OpenValueBinding, this.CloseValueBinding };
            }
        }

        public Binding OpenValueBinding
        {
            get
            {
                return this._openValuesBinding;
            }
            set
            {
                if (this._openValuesBinding != value)
                {
                    this._openValuesBinding = value;
                    base.Dirty = true;
                    base.FirePropertyChanged("OpenValueBinding");
                }
            }
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public DoubleCollection OpenValues
        {
            get
            {
                return (DoubleCollection)base.GetValue(OpenValuesProperty);
            }
            set
            {
                base.SetValue(OpenValuesProperty, value);
            }
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public IEnumerable OpenValuesSource
        {
            get
            {
                return (IEnumerable)base.GetValue(OpenValuesSourceProperty);
            }
            set
            {
                base.SetValue(OpenValuesSourceProperty, value);
            }
        }

        // Nested Types
        public class HLOCDataPoint : XYDataSeries.XYDataPoint
        {
            // Methods
            internal HLOCDataPoint(DataSeries ds, int seriesIndex, int pointIndex, string[] names)
                : base(ds, seriesIndex, pointIndex, names)
            {
            }

            // Properties
            public object Close
            {
                get
                {
                    return base.Series.GetValue(5, base.PointIndex);
                }
            }

            public object High
            {
                get
                {
                    return base.Series.GetValue(3, base.PointIndex);
                }
            }

            public object Low
            {
                get
                {
                    return base.Series.GetValue(2, base.PointIndex);
                }
            }

            public object Open
            {
                get
                {
                    return base.Series.GetValue(4, base.PointIndex);
                }
            }
        }
    }
}
